﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MiniCalc;

namespace MiniCalcTest
{
    [TestClass]
    public class UnitTest1
    {
        private TestContext testContextInstance;

        private Calculator testCalc;
        private int nResult;

        /// <summary>
        /// Gets or sets the test context which provides
        /// Information about and functionality for the current test run.
        /// </summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        [TestInitialize()]
        public void CalculatorTestInitialize()
        {
            Console.Out.WriteLine("CalculatorTestInitialize called");
            testCalc = new Calculator();
        }

        [TestCleanup()]
        public void CalculatorTestCleanup()
        {
            Console.Out.WriteLine("CalculatorTestCleanup");
            testCalc = null;
        }

        //[TestMethod()]
        //public void TestThatFails()
        //{
        //    Console.Out.WriteLine("TestThatFails called");
        //    Assert.Fail("This test is supposed to fail!");
        //}

        //[TestMethod()]
        //public void TestThatSucceeds()
        //{
        //    Console.Out.WriteLine("TestThatSucceeds called");
        //    Assert.IsTrue(true, "This test is supposed to succeed!");
        //}

        [TestMethod()]
        public void TestAdd()
        {
            Console.Out.WriteLine("TestAddition called");
            //test for case of zeros
            Assert.AreEqual(0, testCalc.Add(0, 0), "Adding 0 to 0 should produce 0");
            //test that param ordering isn't important
            Assert.AreEqual(1, testCalc.Add(1, 0), "Adding 1 to 0 should produce 1");
            Assert.AreEqual(1, testCalc.Add(0, 1), "Adding 0 to 1 should produce 1");
            //test for non zero case
            Assert.AreEqual(3, testCalc.Add(1, 2), "Adding 1 to 2 should produce 3");
            try
            {
                nResult = testCalc.Add(int.MaxValue, int.MaxValue);
                Assert.Fail("Should throw a ResultOutOfRangeException");
            }
            catch (ResultOutOfRangeException)
            {
            }
            testCalc = null;
        }

        [TestMethod()]
        public void TestAddNegatives()
        {
            Console.Out.WriteLine("TestAddNegatives called");

            try
            {
                nResult = testCalc.Add(-1, 0);
                Assert.Fail("Should throw a NegativeParameterException");
            }
            catch (NegativeParameterException)
            { }

            try
            {
                nResult = testCalc.Add(0, -1);
                Assert.Fail("Should throw a NegativeParameterException");
            }
            catch (NegativeParameterException)
            { }

            try
            {
                nResult = testCalc.Add(int.MinValue, int.MinValue);
                Assert.Fail("Should throw a NegativeParameterException");
            }
            catch (NegativeParameterException)
            { }
            testCalc = null;
        }

        [TestMethod()]
        public void TestSubtract()
        {
            Assert.AreEqual(0, testCalc.Subtract(0, 0), 
                "Subtracting 0 from 0 should produce 0");
            Assert.AreEqual(1, testCalc.Subtract(0, 1), 
                "Subtracting 0 from 1 should produce 1");

            try
            {
                nResult = testCalc.Subtract(1, 0);
                Assert.Fail("Subtracting 1 from 0 should throw a ResultOutOfRangeException");
            }
            catch (ResultOutOfRangeException)
            { }

            Assert.AreEqual(0, testCalc.Subtract(int.MaxValue, int.MaxValue),
                "Subtracting max value from maxvalue should produce 0");

            try
            {
                nResult = testCalc.Subtract(-1, 0);
                Assert.Fail("Should throw a NegativeParameterException");
            }
            catch (NegativeParameterException)
            { }

            try
            {
                nResult = testCalc.Subtract(0, -1);
                Assert.Fail("Should throw a NegativeParameterException");
            }
            catch (NegativeParameterException)
            { }

            try
            {
                nResult = testCalc.Subtract(int.MinValue, int.MinValue);
                Assert.Fail("Should throw a NegativeParameterException");
            }
            catch (NegativeParameterException)
            { }
        }

        [TestMethod()]
        public void TestCheckForNegativeNumbers()
        {
            try
            {
                testCalc.CheckForNegativeNumbers(0, 0);
            }
            catch (NegativeParameterException)
            {
                Assert.Fail("Zeros are not negative numbers");
            }

            try
            {
                testCalc.CheckForNegativeNumbers(1, 1);
            }
            catch (NegativeParameterException)
            {
                Assert.Fail("1's are not negative numbers");
            }

            try
            {
                testCalc.CheckForNegativeNumbers(int.MaxValue, int.MaxValue);
            }
            catch (NegativeParameterException)
            {
                Assert.Fail("Max vals are not negative numbers");
            }

            try
            {
                testCalc.CheckForNegativeNumbers(-1, 1);
                Assert.Fail("-1's are negative numbers");
            }
            catch (NegativeParameterException)
            { }

            try
            {
                testCalc.CheckForNegativeNumbers(int.MinValue, int.MinValue);
                Assert.Fail("Min vals are negative numbers");
            }
            catch (NegativeParameterException)
            { }
        }

        [TestMethod()]
        public void TestCalculate()
        {
            Assert.AreEqual(2, testCalc.Calculate(1, MiniCalc.Calculator.CalcOperation.Add, 1),
                "Adding 1 to 1 failed");
            Assert.AreEqual(0, testCalc.Calculate(1, MiniCalc.Calculator.CalcOperation.Subtract, 1),
                "Subtracting 1 from 1 failed");
        }
    }
}
